import static org.junit.Assert.*;

import java.awt.*;
import java.util.ArrayList;
import java.util.Random;

import org.junit.Test;



public class MuleTests {

	/*
	 * store is a store object
	 * p is one player (named TestSubject, and he is a red human)
	 * p2 is another player (named PlayerTwo, and he is a blue flapper)
	 * v is an uninitialized player for null checks
	 * rand is a random object
	 * terrain is an int that represents the type of property (Plain, Mountain 1,2, or 3, or River)
	 * prop is a Property object
	 * pub is a Pub object
	 * players is an arrayList of all the players
	 */
	Store store = new Store();
	Player p = new Player(Color.RED, "human", "TestSubject");
	Player p2 = new Player(GameModel.ourBlue, "flapper", "PlayerTwo");
	Player v;
	Random rand = new Random();
	int terrain = rand.nextInt(4) + 1;
	Property prop = new Property(terrain);
	Pub pub = new Pub();
	ArrayList<Player> players = new ArrayList<Player>();
	
	
	 /* edges for buy: not enough money, not enough resource, normal use*/
	
	 /*
	  *  tests to see what happens if the player does not have enough money to purchase a resource
	  *  
	  *  @author Sherman Mathews
	  */	
	@Test (timeout = 300)
	public void testNotEnoughMoneyBuy() {
		p.setMoney(10);
		assertEquals(store.buy(p, 0), false);
		
	}
	
	/*
	 * tests to see what happens if the store is out of inventory
	 * 
	 *  @author Sherman Mathews
	 */
	@Test (timeout = 300)
	public void testNotEnoughResourceBuy() {
		store.getInventory()[0].setAmount(0);
		assertEquals(store.buy(p, 0), false);
		
	}
	
	/*
	 * tests to see if the store can correctly sell a resource to a Player under normal conditions
	 * 
	 * @author Sherman Mathews
	 */
	@Test (timeout = 300)
	public void testNormalBuy() {
		p.setMoney(500);
		store.getInventory()[0].setAmount(1);
		assertEquals(store.buy(p, 0), true);
	}
	/**
	 * Tests a normal sell where the player has an item, sells it,
	 * gains money and loses it from their inventory
	 * 
	 * @author Srindhi Chaganty
	 */
	@Test
	public void testSellNormal(){
		p.setPlayerResource(2, 1);
		int moneyOrig = p.getMoney();
		boolean sell = store.sell(2, p);
		assertTrue(sell);
		assertTrue(p.getPlayerResource(2) == 0);
		assertEquals(p.getMoney(), moneyOrig + 50);
	}
	
	/**
	 * Tests when the player does not have any of a resource and tries to
	 * an item of that number- the sale does not go through
	 * 
	 * @author Srindhi Chaganty
	 */
	@Test
	public void testSellNoItem(){
		p.setPlayerResource(2, 0);
		boolean sell = store.sell(2, p);
		assertTrue(!sell);
		assertTrue(p.getPlayerResource(2) == 0);
	}
	/**
	 * Tests when the player passed in is null, the sale does not go through
	 * 
	 * @author Srindhi Chaganty
	 */
	@Test
	public void testSellNullPlayer(){
		boolean sell = store.sell(2, v);
		assertTrue(!sell);
	}
	/**
	 * Tests that when the itemNumber passed in is out of range, the sale does not go through
	 * 
	 * @author Srindhi Chaganty
	 */
	@Test
	public void testSellOutOfBounds(){
		boolean sell = store.sell(8, p);
		assertTrue(!sell);
	}
	
	/*
	 * tests to see if the player can correctly obtain a property
	 * 
	 * @author Sammy Warrayat
	 */
	@Test (timeout = 300)
	public void testAddProp()
	{
		p.addProperty(null);
		assertEquals(p.getPlayerProperties()[0], null);
		p.addProperty(prop);
		assertEquals(p.getPlayerProperties()[0], prop);
	}
	
	
	/**
	 * Test to make sure the round bonus is correct for round 1. The maximum
	 * a player can get with 10 seconds left on the timer is $100 and the least
	 * they can get is $50.
	 * 
	 * @author Megan Beebe
	 */
	
	@Test (timeout = 300)
	public void testRoundOne() {
		players.add(p);
		players.add(p2);
		GameModel.getInstance().setPlayers(players);
		//round is a Round object
		Round round = new Round();
		round.setRoundNum(1);
		GameModel.getInstance().setRound(round);
		//turn is a Turn object
		Turn turn = new Turn(p, 10);
		GameModel.getInstance().setTurn(turn);
		//money is an int that represents the money
		int money = pub.pubMoney(p);
		assertTrue(money <= 100 && money >= 50);
	}
	
	/**
	 * Test to make sure the round bonus is correct for round four.
	 * The maximum a player can get with 10 seconds left on the timer is
	 * $150 and the minimum is $100.
	 * 
	 * @author Megan Beebe
	 */
	
	@Test (timeout = 300)
	public void testRoundFour() {
		players.add(p);
		players.add(p2);
		GameModel.getInstance().setPlayers(players);
		//round is a Round object
		Round round = new Round();
		round.setRoundNum(4);
		GameModel.getInstance().setRound(round);
		//turn is a Turn object
		Turn turn = new Turn(p, 10);
		GameModel.getInstance().setTurn(turn);
		//money is an int that represents the money
		int money = pub.pubMoney(p);
		assertTrue(money <= 150 && money >= 100);
	}
	
	/**
	 * Test to make sure the round bonus is correct for round eight.
	 * The maximum a player can get with 10 seconds left on the timer is
	 * $200 and the minimum is $150.
	 * 
	 * @author Megan Beebe
	 */
	
	@Test (timeout = 300)
	public void testRoundEight() {
		players.add(p);
		players.add(p2);
		GameModel.getInstance().setPlayers(players);
		//round is a Round object
		Round round = new Round();
		round.setRoundNum(8);
		GameModel.getInstance().setRound(round);
		//turn is a Turn object
		Turn turn = new Turn(p, 10);
		GameModel.getInstance().setTurn(turn);
		//money is an int that represents the money
		int money = pub.pubMoney(p);
		assertTrue(money <= 200 && money >= 150);
	}
	
	/**
	 * Test to make sure the round bonus is correct for round twelve.
	 * The maximum a player can get with 10 seconds left on the timer is
	 * $250 and the minimum is $200.
	 * 
	 * @author Megan Beebe
	 */
	
	@Test (timeout = 300)
	public void testRoundTwelve() {
		players.add(p);
		players.add(p2);
		GameModel.getInstance().setPlayers(players);
		//round is a Round object
		Round round = new Round();
		round.setRoundNum(12);
		GameModel.getInstance().setRound(round);
		//turn is a Turn object
		Turn turn = new Turn(p, 10);
		GameModel.getInstance().setTurn(turn);
		//money is an int that represents the money
		int money = pub.pubMoney(p);
		assertTrue(money <= 250 && money >= 200);
	}
	
	/**
	 * If a player earns over $250 when gambling, their earnings are defaulted to
	 * the max value ($250).
	 * 
	 * @author Megan Beebe
	 */
	@Test (timeout = 300)
	public void testMaxMoney() {
		players.add(p);
		players.add(p2);
		GameModel.getInstance().setPlayers(players);
		//round is a Round object
		Round round = new Round();
		round.setRoundNum(12);
		GameModel.getInstance().setRound(round);
		//turn is a Turn objecy
		Turn turn = new Turn(p, 50);
		GameModel.getInstance().setTurn(turn);
		//money is an int that represents the money
		int money = pub.pubMoney(p);
		assertTrue(money <= 250);
	}
	
	/**
	 * In Round 1, if a player has between 1 and 24 seconds left when they gamble,
	 * they can earn no more than $100 based on the pub algorithm.
	 * 
	 * @author Megan Beebe
	 */
	@Test (timeout = 300)
	public void testTimeLeftOne() {
		players.add(p);
		players.add(p2);
		GameModel.getInstance().setPlayers(players);
		//round is a Round object
		Round round = new Round();
		round.setRoundNum(1);
		GameModel.getInstance().setRound(round);
		//turn is a Turn object
		Turn turn = new Turn(p, 01);
		GameModel.getInstance().setTurn(turn);
		//money is an int that represents the money
		int money = pub.pubMoney(p);
		assertTrue(money <= 100);
	}
	
	/**
	 * In Round 1, if a player has between 25 and 36 seconds left when they gamble,
	 * they can earn no more than $150 and no less than $50 based on the pub algorithm.
	 * 
	 * @author Megan Beebe
	 */
	@Test (timeout = 300)
	public void testTimeLeftTwo() {
		players.add(p);
		players.add(p2);
		GameModel.getInstance().setPlayers(players);
		//round is a Round object
		Round round = new Round();
		round.setRoundNum(1);
		GameModel.getInstance().setRound(round);
		//turn is a Turn object
		Turn turn = new Turn(p, 25);
		GameModel.getInstance().setTurn(turn);
		//money is an int that represents the money
		int money = pub.pubMoney(p);
		System.out.println(money);
		assertTrue(money <= 150 && money >= 50);
	}
	
	/**
	 * In Round 1, if a player has between 37 and 44 seconds left when they gamble,
	 * they can earn no more than $200 and no less than $50 based on the pub algorithm.
	 * 
	 * @author Megan Beebe
	 */
	@Test (timeout = 300)
	public void testTimeLeftThree() {
		players.add(p);
		players.add(p2);
		GameModel.getInstance().setPlayers(players);
		//round is a Round object
		Round round = new Round();
		round.setRoundNum(1);
		GameModel.getInstance().setRound(round);
		//turn is a Turn object
		Turn turn = new Turn(p, 37);
		GameModel.getInstance().setTurn(turn);
		//money is an int that represents the money
		int money = pub.pubMoney(p);
		System.out.println(money);
		assertTrue(money <= 200 && money >= 50);
	}

	/**
	 * In Round 1, if a player has 45 seconds or greater left when they gamble,
	 * they can earn no more than $250 and no less than $50 based on the pub algorithm.
	 * 
	 * @author Megan Beebe
	 */
	@Test (timeout = 300)
	public void testTimeLeftFour() {
		players.add(p);
		players.add(p2);
		GameModel.getInstance().setPlayers(players);
		//round is a Round object
		Round round = new Round();
		round.setRoundNum(1);
		GameModel.getInstance().setRound(round);
		//turn is a Turn object
		Turn turn = new Turn(p, 45);
		GameModel.getInstance().setTurn(turn);
		//money is an int that represents the money
		int money = pub.pubMoney(p);
		System.out.println(money);
		assertTrue(money <= 250 && money >= 50);
	}
	
}